package com.mano233.server.config.json;

import java.lang.annotation.Annotation;
import java.util.Arrays;

import javax.servlet.http.HttpServletResponse;

import com.mano233.server.config.json.annotation.JsonCustomFilter;
import com.mano233.server.config.json.annotation.JsonCustomFilters;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;


/**
 * @author mano233
 */
public class JsonReturnHandler implements HandlerMethodReturnValueHandler {
    private final HandlerMethodReturnValueHandler delegate;

    JsonReturnHandler(HandlerMethodReturnValueHandler delegate) {
        this.delegate = delegate;
    }

    @Override
    public boolean supportsReturnType(MethodParameter returnType) {
        // 如果有我们自定义的 JSON 注解 就用我们这个Handler 来处理
        return delegate.supportsReturnType(returnType);
    }

    @Override
    public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest) throws Exception {
        // 设置这个就是最终的处理类了，处理完不再去找下一个类进行处理
        mavContainer.setRequestHandled(true);

        // 获得注解并执行filter方法 最后返回
        HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
        Annotation[] annotations = returnType.getMethodAnnotations();
        CustomerJsonSerializer jsonSerializer = new CustomerJsonSerializer();
        Arrays.asList(annotations).forEach(a -> {
            // 解析注解，设置过滤条件
            if (a instanceof JsonCustomFilter) {
                JsonCustomFilter json = (JsonCustomFilter) a;
                jsonSerializer.filter(json);
            } else if (a instanceof JsonCustomFilters) {
                // 使用多重注解时，实际返回的是 @Repeatable(JSONS.class) 内指定的 @JSONS 注解
                JsonCustomFilters jsons = (JsonCustomFilters) a;
                Arrays.asList(jsons.value()).forEach(jsonSerializer::filter);
            }
        });

        if (response != null) {
            String json = jsonSerializer.toJson(returnValue);
            response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            response.getWriter().write(json);
        }
    }
}